/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.spi.entity.columnconfig;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.iec.edp.caf.common.environment.EnvironmentUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.UUID;

public class ColumnGenerateConfigLoader {
    private  static final  String separator=File.separator;

    private static final String FILE_RELEATIVE_PATH =String.format("config%1$splatform%1$scommon%1$sbef_columngenerateextend.json",separator);
    private static final String METHODNAME="generateId";

    public ColumnGenerateConfigLoader(){

    }

    public static String getServerPath() {

        return EnvironmentUtil.getServerRTPath();
    }
    public static String fileRead(String path) throws IOException {
        String encoding = "UTF-8";
        File file = new File(path);
        if(!file.exists()){
            return null;
        }
        Long filelength = file.length();
        byte[] filecontent = new byte[filelength.intValue()];
        FileInputStream in = new FileInputStream(file);
        in.read(filecontent);
        in.close();
        String fileContents = new String(filecontent, encoding);
        if (fileContents.startsWith("\ufeff")) {
            fileContents = fileContents.substring(1);
        }

        return fileContents;
    }
    public static ArrayList<ColumnGenerateConfigration> getColumnGenerateConfigration(){

        ObjectMapper mapper=new ObjectMapper();
        String path=getServerPath()+separator+FILE_RELEATIVE_PATH;
        String str= null;
        try {
            str = fileRead(path);
            JsonNode jsonNode = null;
            //文件不存在，返回空
            if(str==null || "".equals(str)){
                return null;
            }
            jsonNode = mapper.readTree(str);
            String metadataConfiguration = jsonNode.findValue("ColumnGenerateConfigration").toString();
            ArrayList<ColumnGenerateConfigration> configration;
            configration=mapper.readValue(metadataConfiguration,new TypeReference<ArrayList<ColumnGenerateConfigration>>(){});
             return configration;
        } catch (IOException e) {
           throw  new RuntimeException("反序列化配置文件内容失败！"+e);
        }
    }

    public static Class getGeneratorClass(String className){
        Class cls;
        try {
            cls=Class.forName(className);
            return cls;
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(String.format("反射类失败，当前类为：%1$s，请确认该类是否被加载！",
                className),e);
        }
    }

    public static Method getMethod(Class cls){
        try {
            Method method=cls.getMethod(METHODNAME);
            return  method;
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(String.format("反射方法失败，当前类为：%1$s，方法名为%2$s",cls.getName(),METHODNAME
                ),e);
        }
    }

    public static String getId(ColumnGenerateInfo info){
        if(info==null || ("".equals(info.getGenerateType()) ||info.getGenerateType()==null)){
            return UUID.randomUUID().toString();
        }
        //配置文件读取
        ArrayList<ColumnGenerateConfigration> configration=ColumnGenerateConfigLoader.getColumnGenerateConfigration();
        if(configration==null || configration.size()==0){
            return UUID.randomUUID().toString();
        }
       return getIdByColumnGenerateInfo(info,configration);
    }

    private static String getIdByColumnGenerateInfo(ColumnGenerateInfo info, ArrayList<ColumnGenerateConfigration> configration) {
        ColumnGenerateConfigration currentConfigration=getCurrentConfig(info,configration);
        String clsName=currentConfigration.getName();
        Class cls=getGeneratorClass(clsName);
        Object obj=getInstance(cls,info,currentConfigration);
        Method method=getMethod(cls);

        return  invokeMethod(obj,method);
    }

    public static Object getInstance(Class cls,ColumnGenerateInfo info,ColumnGenerateConfigration configration){
        Constructor<?> cons = cls.getConstructors()[0];
        try {
            if(info==null||info.getParams().size()==0) {
                return cons.newInstance();
            }
            return cons.newInstance(info.getParams().toArray());

        } catch (InstantiationException|IllegalAccessException|InvocationTargetException e) {
            throw new RuntimeException("类实例化失败！",e);
        }
    }
    private static ColumnGenerateConfigration getCurrentConfig(ColumnGenerateInfo info, ArrayList<ColumnGenerateConfigration> configration) {
        String type=info.getGenerateType();
        ColumnGenerateConfigration generateConfigration=new ColumnGenerateConfigration();
        for (ColumnGenerateConfigration configration1:configration){
            if(type.equals(configration1.getGenerateType())){
                generateConfigration=configration1;
                break;
            }
        }
        return  generateConfigration;
    }

    public static String invokeMethod(Object obj,Method method){
        try {
            return method.invoke(obj).toString();
        } catch (IllegalAccessException|InvocationTargetException e) {
          throw new RuntimeException("反射方法失败！",e);
        }

    }
    public static Object getGuidInstance(Class cls){

        try {
            Constructor<?> cons = cls.getConstructors()[0];
            Object obj=cons.newInstance();
            return obj;
        } catch (InstantiationException |IllegalAccessException| InvocationTargetException e) {
            throw new RuntimeException(String.format("反射类失败，当前类为：%1$s，请确认该类是否被加载！",
                cls.getName()),e);
        }
    }

}
